package com.yuw.utils;

import com.yuw.converter.DateTimeConverter;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Enumeration;

public class MyUtils {

    /**
     * 将form表单中的控件的值通过反射的方式设值给指定的实体类bean
     * 这样，完成form表单向实体类的数据类型转换处理
     * 要求：约定：form表单的name属性值需要和实体类的属性名保持一致【大小写一致】
     *
     * @param request 请求对象
     * @param tClass  被设置的实体类的Class
     * @param <T>     泛型 - 保证通用性
     * @return 设值之后的实体类实例对象
     */
    public static <T> T convertRequest2Bean(HttpServletRequest request, Class<T> tClass) {

        /*******
         * 注册定义了类型转换器：form表单中的String串向目标数据类型的自定义转换 定义BeanUtils的包装类类型的转换器【可以使用匿名内部类】
         ********/
        ConvertUtils.register(new DateTimeConverter(), Date.class); // 使用自定义转换器 转化为目标类型
        ConvertUtils.register(new DateTimeConverter(), LocalDateTime.class); // 使用自定义转换器 转化为目标类型


        // 返回值
        T t = null;
        try {
            // 通过Class获取实体类对象
            t = tClass.newInstance();
            // 把form表单采用http request发送的数据转换为一个实体类bean
            // 获取前台form表单的所有的空间name属性的值
            Enumeration<String> stringEnumerationNames = request.getParameterNames();
            if (stringEnumerationNames != null) {
                // 循环遍历这个集合，使用name属性名，获取对应表单的值
                while (stringEnumerationNames.hasMoreElements()) {
                    // 取出当前name属性元素
                    String strName = stringEnumerationNames.nextElement();
                    // 通过当前name属性元素，获取对应的表单的值
                    String strValue = request.getParameter(strName);
                    // 使用反射，将获取的表单的值设置给实体类
                    if (StringUtils.isNotEmpty(strValue)) {
                        // 因为有约定：表单的name属性值和实体类的属性名一致【要求大小写也一致】，所有可以使用反射进行设值
                        // 第一个参数：反射设值的实体类；第二个参数：被设值的属性名；第三个参数：被设值的属性的值
                        BeanUtils.setProperty(t, strName, strValue);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * 简单工厂：获取一个Class的实例对象 【可以使用Spring框架的IOC 或者 DI 来进行智能处理】
     *
     * @param tClass Class参数
     * @return 实例对象
     */
    public static <T> T getNewInstance(Class<T> tClass) {
        // 默认返回值
        T t = null;
        try {
            t = tClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return t;
    }
}
